
package com.qdlc.p2p.biz.service.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;

import com.qd.p2p.adapter.AdaptedRequestHandleService;
import com.qd.p2p.adapter.param.BankCardListForEnterpriseParameter;
import com.qd.p2p.adapter.param.BankCardListParameter;
import com.qd.p2p.adapter.param.BindingBankCardCodeParameter;
import com.qd.p2p.adapter.param.BindingBankCardForEnterpriseParameter;
import com.qd.p2p.adapter.param.BindingBankCardParameter;
import com.qd.p2p.adapter.param.UnBindingBankCardParameter;
import com.qd.p2p.adapter.response.BankCardListForEnterpriseResponse;
import com.qd.p2p.adapter.response.BankCardListForEnterpriseResponse.Bank;
import com.qd.p2p.adapter.response.BankCardListResponse;
import com.qd.p2p.adapter.response.BindingBankCardCodeResponse;
import com.qd.p2p.adapter.response.BindingBankCardResponse;
import com.qd.p2p.adapter.response.GenericResponse;
import com.qdlc.p2p.biz.service.AccountBankService;
import com.qdlc.p2p.biz.service.AdditionalUserCardService;
import com.qdlc.p2p.biz.service.BindingCardService;
import com.qdlc.p2p.biz.service.DictService;
import com.qdlc.p2p.biz.service.UserInviteService;
import com.qdlc.p2p.biz.util.UserLoginUtil;
import com.qdlc.p2p.common.core.ReturnResult;
import com.qdlc.p2p.common.enums.EnumCardType;
import com.qdlc.p2p.common.util.CollectionUtils;
import com.qdlc.p2p.common.util.DataUtils;
import com.qdlc.p2p.common.util.DateUtil;
import com.qdlc.p2p.common.util.LogFactory;
import com.qdlc.p2p.common.util.MD5Util;
import com.qdlc.p2p.dal.common.SystemConfigHelper;
import com.qdlc.p2p.dal.common.SystemConfigHelper.Nid;
import com.qdlc.p2p.dal.common.model.jpa.PageDataList;
import com.qdlc.p2p.dal.dao.AccountBankDao;
import com.qdlc.p2p.dal.dao.AccountCashDao;
import com.qdlc.p2p.dal.dao.DictDao;
import com.qdlc.p2p.dal.dto.AccountBank;
import com.qdlc.p2p.dal.dto.AccountCash;
import com.qdlc.p2p.dal.dto.Dict;
import com.qdlc.p2p.dal.dto.User;
import com.qdlc.p2p.dal.dto.UserIdentify;
import com.qdlc.p2p.dal.dto.UserInvite;
import com.qdlc.p2p.dal.model.AccountBankModel;
import com.qdlc.p2p.dal.model.UserInviteModel;
import com.qdlc.p2p.dal.param.BindingCardReqestParam;
import com.qdlc.p2p.dal.util.UserTypeUtils;
import com.qdlc.p2p.dal.util.UserUtils;

@Service
public class BindingCardServiceImpl implements BindingCardService{

	private static final Logger log = LogFactory.BINDING_CARD_LOGGER;
	
	public static final String TICKET = "ticket";
	public static final String ACCOUNT_BANK = "binding_card_account_bank";
	
	@Resource
	AdaptedRequestHandleService adaptedPayService;
	
	@Resource
	DictService dictService;
	
	@Resource
	AccountBankService accountBankService;
	
	@Resource
	AccountBankDao accountBankDao;
	
	@Resource
	AccountCashDao accountCashDao;
	
	@Resource
	AdditionalUserCardService additionalUserCardService;
	
	@Resource
	DictDao dictDao;
	
	@Resource
	UserInviteService userInviteService;
	
	/**
	 * [绑卡] 获取绑卡手机验证码
	 * 请求新浪接口，获取手机验证码和ticket，ticket加密后返回到页面
	 * 保存AccountBank对象
	 * @param user
	 * @param bindingCardParam
	 * @return
	 */
	@Override
	public ReturnResult bindingBardForPhoneCode(User user, BindingCardReqestParam bindingCardParam){
		
		//检测参数
		ReturnResult result = checkBindingCardParam(user, bindingCardParam);
		if(result.isError()){
			return result;
		}
		
		// 获取请求参数
		String bankNo = bindingCardParam.getBankNo();
		String mobilePhone = bindingCardParam.getMobilephone();
		String province = bindingCardParam.getProvince();
		String city = bindingCardParam.getCity();
		long dictBankId = bindingCardParam.getDictBankId();
		
        //获取第三方交易ID
        String platformUserId = user.getTppUserCustId();
        if(StringUtils.isBlank(platformUserId)){
        	return new ReturnResult("请先进行实名认证!");
        }
        
        BindingBankCardCodeParameter parameter = new BindingBankCardCodeParameter();
        parameter.setPlatformUserId(platformUserId);
        
        //绑卡发送手机验证码
        BindingBankCardCodeResponse bindResponse = adaptedPayService.sendBindingBankCode(parameter);
        if (bindResponse == null) {
        	return new ReturnResult("系统正繁忙！请稍候重试!");
        }
        
        //请求成功，保存AccountBank记录
        if(bindResponse.isSuccess()) {
            String checkTicket = MD5Util.MD5Encode(String.valueOf(dictBankId).concat("|").concat(province).concat("|").concat(city).concat("|").concat(bankNo).concat("|").concat(mobilePhone), "utf8");
            result = new ReturnResult();
            result.addExtra(TICKET, checkTicket);
            result.setErrorInfo("成功发送验证码!");
        } else {
        	result = new ReturnResult(bindResponse.getResponseMsg());
        }
		
		return result;
	}
	
	/**
	 * [绑卡] 绑卡推进
	 * @param user
	 * @param bindingCardParam
	 * @param ticket
	 * @param phoneCode
	 * @return
	 */
	@Override
	public ReturnResult bindingBankCardAdvance(User user, BindingCardReqestParam bindingCardParam, String ticket, String phoneCode){
		
		// 检测参数
		ReturnResult result = checkBindingCardParam(user, bindingCardParam);
		if(result.isError()){
			return result;
		}
		
		//验证ticket和验证码（验证加密后的ticket，防止篡改）
		result = checkTicketAndPhoneCode(bindingCardParam, ticket, phoneCode);
		if(result.isError()){
			return result;
		}

		//重新绑定，先将以前的卡解绑
		List<AccountBank> list =  accountBankService.list(user.getUserId());
		if(list.size()>0){
			for (AccountBank accountBank:list) {
				if(accountBank.getStatus()== 1){
					accountBankService.disable(user,accountBank.getBankNo());
				}
			}
		}
		
		// 防止重复绑定和篡改其他用户银行卡信息
		String bankNo = bindingCardParam.getBankNo();
		AccountBank ab = accountBankService.findByBankNo(bankNo);
        // 防止重复绑定和篡改其他用户银行卡信息
        if (ab != null ) {
        	if (ab.getStatus() == 1) {
        		return new ReturnResult("该银行卡已绑定，请勿重复绑定");
        	} else if (ab.getStatus() == 0 && user.getUserId() != ab.getUserId()) {
        		return new ReturnResult("用户银行卡信息不匹配!");
        	}
        }
        
        Dict dict = dictService.find(bindingCardParam.getDictBankId());
        String cardId = null;
        
        //企业用户绑卡
        if(UserTypeUtils.isCorporate(user.getUserId())){
        	BindingBankCardForEnterpriseParameter parameter = new BindingBankCardForEnterpriseParameter();
        	parameter.setPlatformUserId(user.getTppUserCustId());
        	parameter.setBankName(dict.getName());
        	parameter.setProvince(bindingCardParam.getProvince());
        	parameter.setCity(bindingCardParam.getCity());
        	parameter.setBankAddress(bindingCardParam.getBankAddress());
        	parameter.setType(1);
        	parameter.setBankNo(bankNo);
        	parameter.setValidateCode(phoneCode);
        	GenericResponse advanceResp = adaptedPayService.bindingBankCardForEnterprise(parameter);
        	if (advanceResp == null) {
        		return new ReturnResult("系统正繁忙！请稍候重试!");
        	}
        	if (!advanceResp.isSuccess()) {
        		return new ReturnResult(advanceResp.getResponseMsg());
        	}
        	//查询绑卡列表
            BankCardListForEnterpriseParameter bankCardListParameter = new BankCardListForEnterpriseParameter();
            bankCardListParameter.setPlatformUserId(user.getTppUserCustId());
            BankCardListForEnterpriseResponse bankCardListResponse = adaptedPayService.queryBankListForEnterprise(bankCardListParameter);
            if(bankCardListResponse == null){
            	return new ReturnResult("系统正繁忙！请稍候重试!");
            }
            if (!bankCardListResponse.isSuccess()) {
                return new ReturnResult(advanceResp.getResponseMsg());
            }
            
            //查询已绑定的银行卡
            List<Bank> bankList = bankCardListResponse.getBankList();
            if(bankList == null || bankList.size() == 0){
            	return new ReturnResult("绑卡失败,请稍候重试!");
            }
            
            //取银行卡后4位
            boolean hasMatched = false;
            String bankNoSuffix = bankNo.substring(bankNo.length() - 4, bankNo.length());
            for(Bank bank: bankList){
            	String bn = bank.getBankNo();
            	if(bankNoSuffix.equals(bn.substring(bn.length() - 4, bn.length()))){
            		hasMatched = true;
            		break;
            	};
            }
            if(!hasMatched){
            	return new ReturnResult("绑卡失败,请稍候重试!");
            }
        }
        //普通用户绑卡
        else{
        	BindingBankCardParameter parameter = new BindingBankCardParameter();
        	parameter.setMobile(user.getMobilePhone());
        	parameter.setBankNo(bankNo);
        	parameter.setPlatformUserId(user.getTppUserCustId());
        	parameter.setValidateCode(phoneCode);
        	BindingBankCardResponse advanceResp = adaptedPayService.bindingBankCard(parameter);
        	if (advanceResp == null) {
        		return new ReturnResult("系统正繁忙！请稍候重试!");
        	}
        	if (!advanceResp.isSuccess()) {
        		return new ReturnResult(advanceResp.getResponseMsg());
        	}
        	
        	cardId = advanceResp.getCardId();
        }
        
        //构将AccountBank对象，并保存到数据库
        AccountBank accountBank = populationAccountBank(user, bindingCardParam);
        accountBank.setBank(dict.getId());
        accountBank.setPicPath("/data/bank/mini/" + dict.getValue() + ".png");
        accountBank.setTppCardId(cardId);

        if (ab == null) {
            accountBankService.save(accountBank);
        } else {
            ab.setAddIp(bindingCardParam.getIp());
			ab.setBank(dict.getId());
			ab.setPicPath("/data/bank/mini/" + dict.getValue() + ".png");
            ab.setAddTime(DateUtil.getNow());
            ab.setStatus(1);
            ab.setTppCardId(cardId);
            accountBankService.update(ab);
        }
		
        result = new ReturnResult();
        result.setErrorInfo("绑卡成功！");

		//当以前没绑过卡才发奖
		if(list.size()<=0){
			//赠送"掌"卡
			additionalUserCardService.giveCard(user, EnumCardType.PALM_WIND_CARD.getType());
			//检测邀请人是否可以发放"柜"卡
			ReturnResult invitedBindingCard = inviteUserBindingCard(user);
			if(invitedBindingCard.isSuccess()){
				User inviteUser = (User)invitedBindingCard.getExtra("inviteUser");
				additionalUserCardService.giveCard(inviteUser, EnumCardType.CABINET_WIND_CARD.getType());
			}
		}

		return result;
	}
	
	
	private ReturnResult checkBindingCardParam(User user, BindingCardReqestParam bindingCardParam){
		
        UserIdentify userIdentify = UserLoginUtil.getUserIdentify();
        if (userIdentify.getRealNameStatus() != 1 && userIdentify.getMobilePhoneStatus() != 1) {
            return new ReturnResult("请您先实名认证!");
        }
        
        long dictBankId = bindingCardParam.getDictBankId();
        if (dictBankId == 0) {
            return new ReturnResult("请选择银行!");
        }
        
        String province = bindingCardParam.getProvince();
        if (StringUtils.isEmpty(province)) {
        	return new ReturnResult("请选择省份!");
        }
        
        String city = bindingCardParam.getCity();
        if (StringUtils.isEmpty(city)) {
        	return new ReturnResult("请选择城市!");
        }
        
        String bankNo = bindingCardParam.getBankNo();
        if (StringUtils.isEmpty(bankNo)) {
        	return new ReturnResult("请输入银行账号!");
        }
        
        String mobilePhone = bindingCardParam.getMobilephone();
        if (StringUtils.isEmpty(mobilePhone)) {
        	return new ReturnResult("请输入手机号!");
        }
        
    /*    //检测绑卡上限
        int countTotal = accountBankService.count(user.getUserId());
        int defaultTotal = SystemConfigHelper.getIntegerValue(Nid.BANK_NUM);
        if(countTotal >= defaultTotal){
        	return new ReturnResult("添加银行卡数不能超过" + defaultTotal + "个!");
        }*/
        
        return ReturnResult.SUCCESS;
	}
	
	private AccountBank populationAccountBank(User user, BindingCardReqestParam bindingCardParam){
		AccountBank accountBank = new AccountBank();
		accountBank.setBank(bindingCardParam.getDictBankId());
		accountBank.setBankNo(bindingCardParam.getBankNo());
		accountBank.setProvince(bindingCardParam.getProvince());
		accountBank.setCity(bindingCardParam.getCity());
		accountBank.setMobilephone(bindingCardParam.getMobilephone());
		accountBank.setUserId(user.getUserId());
		accountBank.setAddTime(DateUtil.getNow());
		accountBank.setAddIp(bindingCardParam.getIp());
        accountBank.setIsSafe(1);
        accountBank.setStatus(1);
		return accountBank;
	}
	
	/**
	 * 检测Ticket和手机验证码
	 * @param bindingCardParam
	 * @param ticket
	 * @param phoneCode
	 * @return
	 */
	private ReturnResult checkTicketAndPhoneCode(BindingCardReqestParam bindingCardParam, String ticket, String phoneCode){
		
		if(StringUtils.isEmpty(ticket)){
			return new ReturnResult("请求有误,请重新获取验证码!");
		}
		if(StringUtils.isEmpty(phoneCode)){
			return new ReturnResult("验证码有误,请重新获取验证码!");
		}
		
        long dictBankId = bindingCardParam.getDictBankId();
        String province = bindingCardParam.getProvince();
        String city = bindingCardParam.getCity();
        String bankNo = bindingCardParam.getBankNo();
        String mobilePhone = bindingCardParam.getMobilephone();
        String checkTicket = MD5Util.MD5Encode(String.valueOf(dictBankId).concat("|").concat(province).concat("|").concat(city).concat("|").concat(bankNo).concat("|").concat(mobilePhone), "utf8");
        if (!checkTicket.equals(ticket)) {
        	return new ReturnResult("非法请求,请重新获取验证码!");
        }
        
        return ReturnResult.SUCCESS;
	}
	
	/**
	 * [解卡] 获取解绑短信验证码
	 * @param user
	 * @return
	 */
	@Override
	public ReturnResult disableBankForPhoneCode(User user){
        
		//绑卡发送手机验证码
		BindingBankCardCodeParameter parameter = new BindingBankCardCodeParameter();
        parameter.setPlatformUserId(user.getTppUserCustId());
        BindingBankCardCodeResponse bindResponse = adaptedPayService.sendBindingBankCode(parameter);
        if (bindResponse == null) {
        	return new ReturnResult("系统正繁忙！请稍候重试!");
        }
        
        ReturnResult result = new ReturnResult();
        if(bindResponse.isSuccess()) {
            result.setErrorInfo("成功发送验证码!");
        } else {
        	result.setError(true);
        	result = new ReturnResult(bindResponse.getResponseMsg());
        }
		return result;
	}
	
	/**
	 * [解卡] 解除绑卡
	 * @param user
	 * @param bankNo
	 * @return
	 */
	@Override
	public ReturnResult disableBank(User user, String bankNo, String phoneCode){
		
		AccountBank accountBank = accountBankService.find(user.getUserId(), bankNo);
		String cardId = accountBank.getTppCardId();
		UnBindingBankCardParameter parameter = new UnBindingBankCardParameter();
		parameter.setCardId(cardId);
		parameter.setPlatformUserId(user.getTppUserCustId());
		parameter.setValidateCode(phoneCode);
		GenericResponse response = adaptedPayService.unBindingBankCard(parameter);
		if(response.isSuccess()){
			accountBankService.disable(user, bankNo);
		}else{
			return new ReturnResult(response.getResponseMsg());
		}
		
		return ReturnResult.SUCCESS;
	}
	
	/**
	 * [绑卡] 查询已经绑定的卡，正在提现的卡会设置不能解绑
	 * @param user
	 * @return
	 */
	@Override
	public List<AccountBankModel> findCardByUserId(User user){
		long userId = user.getUserId();
		List<AccountBank> list = accountBankDao.list(userId);
		if(list == null || list.size() == 0){
			return Collections.emptyList();
		}
		
		// 查询正在审核中的提现记录
		List<AccountCash> cashList = accountCashDao.findByUserId(userId, 0);
		Set<String> bankNoCashingSet = new HashSet<String>();
		if(cashList != null){
			for(AccountCash cash: cashList){
				bankNoCashingSet.add(cash.getBankNo());
			}
		}
		
		List<AccountBankModel> modelList = new ArrayList<AccountBankModel>();
		for(AccountBank bank: list){
			AccountBankModel bankmodel = AccountBankModel.instance(bank);
			Dict dict = dictDao.find(bankmodel.getBank());
			bankmodel.setBankName(dict.getName());
			// 如果改银行卡和正在提现的信息一致，不可解绑银行卡
			if(bankNoCashingSet.contains(bank.getBankNo())){
				bankmodel.setCanDisable(false);
			}else{
				bankmodel.setCanDisable(true);
			}
			modelList.add(bankmodel);
		}
		return modelList;
	}

	@Override
	public ReturnResult disableBardForPhoneCode(User user) {
		ReturnResult result = null;
		//获取第三方交易ID
		String platformUserId = user.getTppUserCustId();
		if(StringUtils.isBlank(platformUserId)){
			return new ReturnResult("请先进行实名认证!");
		}

		BindingBankCardCodeParameter parameter = new BindingBankCardCodeParameter();
		parameter.setPlatformUserId(platformUserId);

		//绑卡发送手机验证码
		BindingBankCardCodeResponse bindResponse = adaptedPayService.sendBindingBankCode(parameter);
		if (bindResponse == null) {
			return new ReturnResult("系统正繁忙！请稍候重试!");
		}
		//请求成功，保存AccountBank记录
		if(bindResponse.isSuccess()) {
			result = new ReturnResult();
			result.setErrorInfo("成功发送验证码!");
		} else {
			result = new ReturnResult(bindResponse.getResponseMsg());
		}
		return result;
	}

	@Override
	public ReturnResult disableBankForEnterprise(User user, String phoneCode) {
		List<AccountBank> bankList = accountBankService.list(user.getUserId());
		AccountBank unBank = null;
		for (AccountBank bank :bankList) {
			if(bank.getStatus() == 1){
				unBank = bank;
				break;
			}
		}
		if(unBank == null){
			return new ReturnResult("暂无可解绑的银行卡号");
		}
		Dict dict = dictService.find(unBank.getBank());
		BindingBankCardForEnterpriseParameter parameter = new BindingBankCardForEnterpriseParameter();
		parameter.setPlatformUserId(user.getTppUserCustId());
		parameter.setBankName(dict.getName());
		parameter.setProvince(unBank.getProvince());
		parameter.setCity(unBank.getCity());
		parameter.setBankAddress("无");
		parameter.setType(0);
		parameter.setBankNo(unBank.getBankNo());
		parameter.setValidateCode(phoneCode);
		GenericResponse advanceResp = adaptedPayService.bindingBankCardForEnterprise(parameter);
		if (advanceResp == null) {
			return new ReturnResult("系统正繁忙！请稍候重试!");
		}
		if (!advanceResp.isSuccess()) {
			return new ReturnResult(advanceResp.getResponseMsg());
		}
		accountBankService.disable(user,unBank.getBankNo());
		return ReturnResult.SUCCESS;
	}

	/**
	 * 邀请人绑卡活动
	 * @param user
	 * @return 
	 */
	private ReturnResult inviteUserBindingCard(User user){
		
		//获取当前用户的邀请人信息
		UserInvite invite = userInviteService.findByUserId(user.getUserId());
		if(invite == null){
			return ReturnResult.FAILURE;
		}
		
		User inviteUser = UserUtils.getUserById(invite.getInviteUser());
		
		//被邀请人列表信息
		PageDataList<UserInviteModel> invites = userInviteService.findByInviteUser(inviteUser, 1);
		List<UserInviteModel> inviteList = invites.getList();
		if(inviteList == null || inviteList.size() == 0){
			return ReturnResult.FAILURE;
		}
		
		//获取被邀请人，并判断是否绑定银行卡
		int bindingCardCount = 0;
		for(UserInviteModel m: inviteList){
			List<AccountBank> bankList = accountBankService.list(m.getUserId());
			if(CollectionUtils.isNotNullOrEmpty(bankList)){
				bindingCardCount ++;
			}
		}
		
		//获取邀请人绑卡个数，如果到达配置数量，则可以参与活动
		int configCount = DataUtils.toInt(SystemConfigHelper.getIntegerValue(Nid.INVITE_BINDING_CARD_COUNT), 3);
		if(bindingCardCount == configCount){
			ReturnResult result = new ReturnResult();
			result.addExtra("inviteUser", inviteUser);
			return result;
		}

		return ReturnResult.FAILURE;
	}


}
